{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "![](https://raw.githubusercontent.com/Qinbf/tf-model-zoo/master/README_IMG/01.jpg)\n",
    "AI MOOC： **www.ai-xlab.com**  \n",
    "如果你也是AI爱好者，可以添加我的微信一起交流：**sdxxqbf**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 载入数据\n",
    "data = np.genfromtxt(\"kmeans.txt\", delimiter=\" \")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 计算距离 \n",
    "def euclDistance(vector1, vector2):  \n",
    "    return np.sqrt(sum((vector2 - vector1)**2))\n",
    "  \n",
    "# 初始化质心\n",
    "def initCentroids(data, k):  \n",
    "    numSamples, dim = data.shape\n",
    "    # k个质心，列数跟样本的列数一样\n",
    "    centroids = np.zeros((k, dim))  \n",
    "    # 随机选出k个质心\n",
    "    for i in range(k):  \n",
    "        # 随机选取一个样本的索引\n",
    "        index = int(np.random.uniform(0, numSamples))  \n",
    "        # 作为初始化的质心\n",
    "        centroids[i, :] = data[index, :]  \n",
    "    return centroids  \n",
    "  \n",
    "# 传入数据集和k的值\n",
    "def kmeans(data, k):  \n",
    "    # 计算样本个数\n",
    "    numSamples = data.shape[0]   \n",
    "    # 样本的属性，第一列保存该样本属于哪个簇，第二列保存该样本跟它所属簇的误差\n",
    "    clusterData = np.array(np.zeros((numSamples, 2)))  \n",
    "    # 决定质心是否要改变的变量\n",
    "    clusterChanged = True  \n",
    "  \n",
    "    # 初始化质心  \n",
    "    centroids = initCentroids(data, k)  \n",
    "  \n",
    "    while clusterChanged:  \n",
    "        clusterChanged = False  \n",
    "        # 循环每一个样本 \n",
    "        for i in range(numSamples):  \n",
    "            # 最小距离\n",
    "            minDist  = 100000.0  \n",
    "            # 定义样本所属的簇\n",
    "            minIndex = 0  \n",
    "            # 循环计算每一个质心与该样本的距离\n",
    "            for j in range(k):  \n",
    "                # 循环每一个质心和样本，计算距离\n",
    "                distance = euclDistance(centroids[j, :], data[i, :])  \n",
    "                # 如果计算的距离小于最小距离，则更新最小距离\n",
    "                if distance < minDist:  \n",
    "                    minDist  = distance  \n",
    "                    # 更新样本所属的簇\n",
    "                    minIndex = j  \n",
    "                    # 更新最小距离\n",
    "                    clusterData[i, 1] = distance\n",
    "              \n",
    "            # 如果样本的所属的簇发生了变化\n",
    "            if clusterData[i, 0] != minIndex:  \n",
    "                # 质心要重新计算\n",
    "                clusterChanged = True\n",
    "                # 更新样本的簇\n",
    "                clusterData[i, 0] = minIndex\n",
    "  \n",
    "        # 更新质心\n",
    "        for j in range(k):  \n",
    "            # 获取第j个簇所有的样本所在的索引\n",
    "            cluster_index = np.nonzero(clusterData[:, 0] == j)\n",
    "            # 第j个簇所有的样本点\n",
    "            pointsInCluster = data[cluster_index]  \n",
    "            # 计算质心\n",
    "            centroids[j, :] = np.mean(pointsInCluster, axis = 0) \n",
    "#         showCluster(data, k, centroids, clusterData)\n",
    "  \n",
    "    return centroids, clusterData  \n",
    "  \n",
    "# 显示结果 \n",
    "def showCluster(data, k, centroids, clusterData):  \n",
    "    numSamples, dim = data.shape  \n",
    "    if dim != 2:  \n",
    "        print(\"dimension of your data is not 2!\")  \n",
    "        return 1  \n",
    "  \n",
    "    # 用不同颜色形状来表示各个类别\n",
    "    mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']  \n",
    "    if k > len(mark):  \n",
    "        print(\"Your k is too large!\")  \n",
    "        return 1  \n",
    "  \n",
    "    # 画样本点  \n",
    "    for i in range(numSamples):  \n",
    "        markIndex = int(clusterData[i, 0])  \n",
    "        plt.plot(data[i, 0], data[i, 1], mark[markIndex])  \n",
    "  \n",
    "    # 用不同颜色形状来表示各个类别\n",
    "    mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']  \n",
    "    # 画质心点 \n",
    "    for i in range(k):  \n",
    "        plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 20)  \n",
    "  \n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "F:\\Anaconda3\\lib\\site-packages\\numpy\\core\\fromnumeric.py:2957: RuntimeWarning: Mean of empty slice.\n",
      "  out=out, **kwargs)\n",
      "F:\\Anaconda3\\lib\\site-packages\\numpy\\core\\_methods.py:73: RuntimeWarning: invalid value encountered in true_divide\n",
      "  ret, rcount, out=ret, casting='unsafe', subok=False)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cluster complete!\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x2876c7fc908>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 设置k值\n",
    "k = 4  \n",
    "\n",
    "min_loss = 10000\n",
    "min_loss_centroids = np.array([])\n",
    "min_loss_clusterData = np.array([])\n",
    "\n",
    "for i in range(50):\n",
    "    # centroids 簇的中心点 \n",
    "    # cluster Data样本的属性，第一列保存该样本属于哪个簇，第二列保存该样本跟它所属簇的误差\n",
    "    centroids, clusterData = kmeans(data, k)  \n",
    "    loss = sum(clusterData[:,1])/data.shape[0]\n",
    "    if loss < min_loss:\n",
    "        min_loss = loss\n",
    "        min_loss_centroids = centroids\n",
    "        min_loss_clusterData = clusterData\n",
    "        \n",
    "#     print('loss',min_loss)\n",
    "print('cluster complete!')      \n",
    "centroids = min_loss_centroids\n",
    "clusterData = min_loss_clusterData\n",
    "\n",
    "# 显示结果\n",
    "showCluster(data, k, centroids, clusterData)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 做预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [0, 1],\n",
       "       [0, 1],\n",
       "       [0, 1]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 做预测\n",
    "x_test = [0,1]\n",
    "np.tile(x_test,(k,1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 3.53973889,  3.89384326],\n",
       "       [-2.6265299 , -2.10868015],\n",
       "       [ 2.46154315, -1.78737555],\n",
       "       [-2.65077367,  3.79019029]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 误差\n",
    "np.tile(x_test,(k,1))-centroids"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[12.52975144, 15.16201536],\n",
       "       [ 6.89865932,  4.44653198],\n",
       "       [ 6.05919468,  3.19471136],\n",
       "       [ 7.02660103, 14.3655424 ]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 误差平方\n",
    "(np.tile(x_test,(k,1))-centroids)**2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([27.6917668 , 11.34519129,  9.25390604, 21.39214343])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 误差平方和\n",
    "((np.tile(x_test,(k,1))-centroids)**2).sum(axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 最小值所在的索引号\n",
    "np.argmin(((np.tile(x_test,(k,1))-centroids)**2).sum(axis=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def predict(datas):\n",
    "    return np.array([np.argmin(((np.tile(data,(k,1))-centroids)**2).sum(axis=1)) for data in datas])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 画出簇的作用区域"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\nhwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x287691b6b70>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 获取数据值所在的范围\n",
    "x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1\n",
    "y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1\n",
    "\n",
    "# 生成网格矩阵\n",
    "xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),\n",
    "                     np.arange(y_min, y_max, 0.02))\n",
    "\n",
    "z = predict(np.c_[xx.ravel(), yy.ravel()])# ravel与flatten类似，多维数据转一维。flatten不会改变原始数据，ravel会改变原始数据\n",
    "z = z.reshape(xx.shape)\n",
    "# 等高线图\n",
    "cs = plt.contourf(xx, yy, z)\n",
    "# 显示结果\n",
    "showCluster(data, k, centroids, clusterData)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
